﻿/*  
	------------------------------------------------------------------------
	 NQ Core Library
	
	 Homepage: http://www.awzhome.de/
	------------------------------------------------------------------------
	
	This Source Code Form is subject to the terms of the Mozilla Public
	License, v. 2.0. If a copy of the MPL was not distributed with this
	file, You can obtain one at http://mozilla.org/MPL/2.0/.
   
	The Original Code is code of NQ Core Library.

	The Initial Developer of the Original Code is Andreas Weizel.
	Portions created by the Initial Developer are
	Copyright (C) 2012 Andreas Weizel. All Rights Reserved.
	
	Contributor(s): (none)
	
	------------------------------------------------------------------------
*/

using System;
namespace AWZhome.NQ.Core.Fluent
{

	/// <summary>
	/// Wraps a "lazy created" service instance to be used with the NQ fluent interface.
	/// </summary>
	/// <typeparam name="T">Type of the service instance.</typeparam>
	public class LazyCreatedServiceWrapper<T> : ServiceInstanceWrapper<T>
	{
		private bool _createDirect = false;
		private Type _serviceInterface;

		internal LazyCreatedServiceWrapper()
		{
			_serviceInterface = typeof(T);
		}

		/// <summary>
		/// Returns the wrapped service instance.
		/// </summary>
		//[Obsolete("Please use Instance property instead.")]
		public override T To
		{
			get
			{
				this.CreateInternalInstance();
				return base.To;
			}
		}

		/// <summary>
		/// Returns the wrapped service instance.
		/// </summary>
		public override T Instance
		{
			get
			{
				this.CreateInternalInstance();
				return base.To;
			}
		}

		/// <summary>
		/// Uses a special type as registered service interface.
		/// </summary>
		/// <param name="serviceInterface">
		/// Registered service
		/// interface as <see cref="System.Type">Type</see> reference.
		/// </param>
		/// <returns>The instance of the wrapper.</returns>
		public virtual LazyCreatedServiceWrapper<T> UsingType(Type serviceInterface)
		{
			_serviceInterface = serviceInterface;
			return this;
		}

		/// <summary>
		/// Returns an <see cref="AWZhome.NQ.Core.INQServiceInfo">INQServiceInfo</see>
		/// instance describing the service the object belongs to.
		/// </summary>
		public override INQServiceInfo MetaInfo
		{
			get
			{
				return NQServiceManager.Instance.GetServiceInfo(_serviceInterface);
			}
		}

		/// <summary>
		/// Returns a log wrapper to access the log functionality
		/// of NQ Service Manager.
		/// </summary>
		public override LogWrapper<T> Log
		{
			get
			{
				this.CreateInternalInstance();
				return base.Log;
			}
		}

		/// <summary>
		/// Lets the wrapper create a direct instance without
		/// resolving substitutions.
		/// </summary>
		public LazyCreatedServiceWrapper<T> Directly
		{
			get
			{
				_createDirect = true;
				return this;
			}
		}

		/// <summary>
		/// Creates a service instance that is dependent on another instance.
		/// </summary>
		/// <typeparam name="P">Type of the parent service.</typeparam>
		/// <param name="parent">Instance of the parent service, that is passed to created service instance.</param>
		/// <returns>A <see cref="AWzhome.NQ.Core.Fluent.ServiceInstanceWrapper#T">ServiceInstanceWrapper&lt;T&gt;</see>
		/// object to perform other operations on that service.</returns>
		public ServiceInstanceWrapper<T> DependentOn<P>(P parent)
		{
			if (_createDirect)
			{
				_serviceObject = NQServiceManager.Instance.CreateDependentServiceDirect<T, P>(_serviceInterface, parent);
			}
			else
			{
				_serviceObject = NQServiceManager.Instance.CreateDependentService<T, P>(_serviceInterface, parent);
			}
			return this;
		}

		/// <summary>
		/// Creates a service instance that is dependent on two another instances.
		/// </summary>
		/// <typeparam name="P1">Type of the first parent service.</typeparam>
		/// <typeparam name="P2">Type of the second parent service.</typeparam>
		/// <param name="parent1">Instance of the first parent service, that is passed to created service instance.</param>
		/// <param name="parent2">Instance of the second parent service, that is passed to created service instance.</param>
		/// <returns>A <see cref="AWzhome.NQ.Core.Fluent.ServiceInstanceWrapper#T">ServiceInstanceWrapper&lt;T&gt;</see>
		/// object to perform other operations on that service.</returns>
		public ServiceInstanceWrapper<T> DependentOn<P1, P2>(P1 parent1, P2 parent2)
		{
			if (_createDirect)
			{
				_serviceObject = NQServiceManager.Instance.CreateDependentServiceDirect2<T, P1, P2>(_serviceInterface, parent1, parent2);
			}
			else
			{
				_serviceObject = NQServiceManager.Instance.CreateDependentService2<T, P1, P2>(_serviceInterface, parent1, parent2);
			}
			return this;
		}

		/// <summary>
		/// Invokes (calls the invoke method of) the wrapped service instance.
		/// </summary>
		/// <returns>The instance of the wrapper.</returns>
		public override ServiceInstanceWrapper<T> Invoke()
		{
			this.CreateInternalInstance();
			return base.Invoke();
		}

		/// <summary>
		/// Quits (calls the quit method of) the wrapped service instance.
		/// </summary>
		/// <returns>The instance of the wrapper.</returns>
		public override ServiceInstanceWrapper<T> Quit()
		{
			this.CreateInternalInstance();
			return base.Quit();
		}

		private void CreateInternalInstance()
		{
			if (_serviceObject == null)
			{
				if (_createDirect)
				{
					_serviceObject = NQServiceManager.Instance.CreateServiceDirect<T>(_serviceInterface);
				}
				else
				{
					_serviceObject = NQServiceManager.Instance.CreateService<T>(_serviceInterface);
				}
			}
		}
	}
}
